package com.cellulam.framework.core.model;

import com.cellulam.framework.core.enums.JdbcType;
import com.cellulam.framework.core.enums.Operator;
import com.cellulam.framework.core.enums.SortType;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;

import java.util.List;
import java.util.Map;

/**
 * 分页查询
 *
 * @param <T>
 */
public class PagerRequest<T> {
    public PagerRequest() {
    }

    public PagerRequest(int page, int pageSize) {
        this.page = page;
        this.pageSize = pageSize;
    }

    /**
     * 第几页,从1开始
     * 默认 1
     */
    private int page;

    /**
     * 每页多少条
     * 默认 20
     */
    private int pageSize;

    /**
     * 排序
     * key: 排序字段，value: 排序方式(SortType, 1: 正序，2: 倒序，默认倒序)
     * 废弃，多个字段排序会有问题
     */
    @Deprecated
    private Map<String, Integer> sort;


    public PagerRequest<T> setSortFields(List<PagerSort> sortFields) {
        this.sortFields = sortFields;
        return this;
    }

    private List<PagerSort> sortFields;


    /**
     * 自定义查询条件
     */
    private List<PagerCondition> conditions;

    /**
     * 添加自定义查询条件
     *
     * @param field
     * @param value
     */
    public PagerRequest<T> addCondition(String field, Object value) {
        return this.addCondition(field, value, Operator.EQUAL);
    }

    /**
     * 添加自定义查询条件
     *
     * @param field
     * @param value
     * @param operator
     */
    public PagerRequest<T> addCondition(String field, Object value, Operator operator) {
        return this.addCondition(field, value, operator, JdbcType.VARCHAR);
    }

    /**
     * 添加自定义查询条件
     *
     * @param field
     * @param value
     * @param operator
     * @param jdbcType
     */
    public PagerRequest<T> addCondition(String field, Object value, Operator operator, JdbcType jdbcType) {
        if (this.conditions == null) {
            this.conditions = Lists.newArrayList();
        }
        this.conditions.add(PagerCondition.builder()
                .field(field)
                .value(value)
                .operator(operator.getCode())
                .jdbcType(jdbcType.getCode())
                .build());
        return this;
    }

    /**
     * 查询条件
     */
    private T criteria;

    public int getPage() {
        return this.page;
    }

    public void setPage(int page) {
        this.page = page > 0 ? page : 1;
    }

    public int getPageSize() {
        return pageSize;
    }

    public void setPageSize(int pageSize) {
        this.pageSize = pageSize > 0 ? pageSize : PagerCriteria.DEFAULT_LIMIT;
    }

    public List<PagerSort> getSortFields() {
        return this.sortFields;
    }

    public Map<String, Integer> getSort() {
        return sort;
    }

    public PagerRequest<T> addSort(String field, SortType sortType) {
        if (this.sort == null) {
            this.sort = Maps.newHashMap();
        }
        if (this.sortFields == null) {
            this.sortFields = Lists.newLinkedList();
        }
        this.sort.put(field, sortType.getCode());
        this.sortFields.add(PagerSort.builder()
                .sortType(sortType.getCode())
                .field(field)
                .build());
        return this;
    }

    @Deprecated
    public void setSort(Map<String, Integer> sort) {
        if (sort != null) {
            for (String key : sort.keySet()) {
                SortType sortType = SortType.valueOf(sort.get(key));
                if (sortType == null) {
                    sortType = PagerCriteria.DEFAULT_SORT_TYPE;
                }
                this.addSort(key, sortType);
            }
        }
    }

    public T getCriteria() {
        return criteria;
    }

    public PagerRequest<T> setCriteria(T criteria) {
        this.criteria = criteria;
        return this;
    }

    public PagerCriteria toCriteria(Object criteria) {
        PagerCriteria pagerCriteria = new PagerCriteria<>(this.pageSize, (this.page - 1) * this.pageSize);
        pagerCriteria.setCriteria(criteria);
        if (this.sortFields != null && !this.sortFields.isEmpty()) {
            this.sortFields.forEach(x -> pagerCriteria.addSort(x.getField(), x.getSortType()));
        }
        if (!CollectionUtils.isEmpty(this.conditions)) {
            this.conditions.forEach(x -> pagerCriteria.addCondition(x.getField(), x.getValue(), x.getOperator(), x.getJdbcType()));
        }
        return pagerCriteria;
    }
}
